<?php
declare (strict_types = 1);

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Db;
use app\service\TopviewApiService;

class CheckMarketingVideoTasks extends Command
{
    protected function configure()
    {
        $this->setName('check:marketing-video-tasks')
            ->setDescription('检查营销视频任务状态');
    }

    protected function execute(Input $input, Output $output)
    {
        $output->writeln('开始检查营销视频任务状态...');
        
        $apiService = new TopviewApiService();
        $checkedReplace = 0;
        $checkedVideo = 0;
        $checkedBg = 0;
        
        try {
            // 第一步：检查去背景任务，完成后自动提交图片替换任务
            $bgTasks = Db::name('marketing_video_unified_tasks')
                ->where('bg_remove_status', 1) // 处理中
                ->where('bg_remove_task_id', '<>', '')
                ->select();

            foreach ($bgTasks as $task) {
                try {
                    $output->writeln("检查去背景任务: {$task['bg_remove_task_id']}");

                    $bgResult = $apiService->queryRemoveBackgroundTask($task['bg_remove_task_id']);

                    if (!isset($bgResult['status'])) {
                        throw new \Exception('API返回结果格式错误');
                    }

                    if ($bgResult['status'] === 'success') {
                        // 取到无背景图片与mask的fileId
                        $withoutBgFileId = $bgResult['bgRemovedImageFileId'] ?? null;
                        $maskFileId = $bgResult['maskImageFileId'] ?? null;

                        // 更新DB标记去背景完成
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'bg_remove_status' => 2,
                                'product_image_without_bg_file_id' => $withoutBgFileId,
                                'mask_image_file_id' => $maskFileId,
                                'update_time' => date('Y-m-d H:i:s')
                            ]);

                        // 自动提交图片替换任务（带上新字段和模式）
                        
                        $submitParams = [
                            'productImageFileId' => $task['product_image_file_id'],
                            'productImageWithoutBackgroundFileId' => $withoutBgFileId,
                            'generateImageMode' => 'auto'
                        ];
                        if (!empty($task['avatar_id'])) {
                            $submitParams['avatarId'] = $task['avatar_id'];
                        }
                        if (!empty($task['template_image_file_id'])) {
                            $submitParams['templateImageFileId'] = $task['template_image_file_id'];
                        }
                        if (!empty($task['user_face_image_file_id'])) {
                            $submitParams['userFaceImageFileId'] = $task['user_face_image_file_id'];
                        }
                        // if (!empty($task['image_edit_prompt'])) {
                            // $submitParams['imageEditPrompt'] = $task['image_edit_prompt'];
                            $submitParams['generateImageMode'] = 'auto';
                        // }

                        $submitResult = $apiService->submitImageReplaceTask($submitParams);

                        // 写入替换任务信息
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'replace_task_id' => $submitResult['result']['taskId'] ?? null,
                                'replace_status' => 1, // 处理中
                                'overall_status' => 1,
                                'update_time' => date('Y-m-d H:i:s')
                            ]);

                        $output->writeln("去背景任务 {$task['bg_remove_task_id']} 完成，已提交图片替换任务");
                        $checkedBg++;

                    } elseif ($bgResult['status'] === 'failed') {
                        // 标记失败
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'bg_remove_status' => 3,
                                'overall_status' => 5,
                                'update_time' => date('Y-m-d H:i:s')
                            ]);

                        $output->writeln("去背景任务 {$task['bg_remove_task_id']} 失败");
                        $checkedBg++;
                    }

                } catch (\Exception $e) {
                    $output->writeln("检查去背景任务 {$task['bg_remove_task_id']} 出错: " . $e->getMessage());
                }
            }

            // 第二步：检查图片替换任务
            $replaceTasks = Db::name('marketing_video_unified_tasks')
                ->where('replace_status', 1) // 处理中
                ->where('replace_task_id', '<>', '')
                ->select();

            foreach ($replaceTasks as $task) {
                try {
                    $output->writeln("检查图片替换任务: {$task['replace_task_id']}");
                    
                    // 调用API查询任务状态
                    $apiResult = $apiService->getImageReplaceResult($task['replace_task_id']);
                    
                    // 检查API返回结果的结构
                    if (!isset($apiResult['result']['status'])) {
                        throw new \Exception('API返回结果格式错误');
                    }
                    
                    $status = $apiResult['result']['status'];
                    if ($status === 'success') { // 已完成
                        $ossService = new \app\service\OssService();
                        $resultImages = [];
                        
                        foreach ($apiResult['result']['replaceProductResult'] as $item) {
                            if (isset($item['url'])) {
                                // 从URL下载图片（带重试机制）
                                $imageContent = $this->downloadFileWithRetry($item['url']);
                                if ($imageContent === false) {
                                    throw new \Exception('下载图片失败: ' . $item['url']);
                                }
                                
                                // 生成OSS对象名
                                $objectName = 'marketing/replace/' . date('Ymd') . '/' . uniqid() . '.jpg';
                                
                                // 创建临时文件
                                $tempFile = tempnam(sys_get_temp_dir(), 'img_');
                                file_put_contents($tempFile, $imageContent);
                                
                                try {
                                    // 上传到OSS
                                    $ossUrl = $ossService->putObject($objectName, $tempFile);
                                    
                                    // 保存结果
                                    $resultImages[] = [
                                        'imageId' => $item['imageId'],
                                        'url' => $ossUrl,
                                        'faceExistence' => $item['faceExistence'] ?? false
                                    ];
                                } finally {
                                    // 清理临时文件
                                    @unlink($tempFile);
                                }
                            }
                        }
                        // 更新任务状态
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'replace_status' => 2,
                                'overall_status' => 2, // 图片替换完成
                                'result_images' => json_encode($resultImages ?? []),
                                'replace_complete_time' => date('Y-m-d H:i:s'),
                                'update_time' => date('Y-m-d H:i:s')
                            ]);
                        
                        $output->writeln("图片替换任务 {$task['replace_task_id']} 已完成");
                        $checkedReplace++;
                        
                    } elseif ($status === 'failed') { // 失败
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'replace_status' => 3,
                                'overall_status' => 5, // 失败
                                'replace_error_msg' => $apiResult['message'] ?? '图片替换失败',
                                'update_time' => date('Y-m-d H:i:s')
                            ]);
                        
                        $output->writeln("图片替换任务 {$task['replace_task_id']} 失败: " . ($apiResult['message'] ?? '未知错误'));
                        $checkedReplace++;
                    }
                    
                } catch (\Exception $e) {
                    $output->writeln("检查图片替换任务 {$task['replace_task_id']} 出错: " . $e->getMessage());
                }
            }

            // 检查视频生成任务
            $videoTasks = Db::name('marketing_video_unified_tasks')
                ->where('video_status', 1) // 处理中
                ->where('video_task_id', '<>', '')
                ->select();

            foreach ($videoTasks as $task) {
                try {
                    $output->writeln("检查视频生成任务: {$task['video_task_id']}");
                    
                    // 调用API查询任务状态
                    $result = $apiService->queryImage2VideoTask($task['video_task_id']);
                    
                    // 检查API返回结果的结构
                    if (!isset($result['status'])) {
                        throw new \Exception('API返回结果格式错误');
                    }
                    
                    if ($result['status'] == 'success') { // 已完成
                        // 上传视频到OSS
                        $ossService = new \app\service\OssService();
                        
                        // 上传预览视频
                        // if (!empty($result['result']['previewVideoUrl'])) {
                        //     $previewVideoContent = file_get_contents($result['result']['previewVideoUrl']);
                        //     $previewVideoPath = 'marketing_videos/preview/' . date('Ymd') . '/' . uniqid() . '.mp4';
                            
                        //     // 创建临时文件
                        //     $tempFile = tempnam(sys_get_temp_dir(), 'preview_');
                        //     file_put_contents($tempFile, $previewVideoContent);
                            
                        //     try {
                        //         $previewVideoUrl = $ossService->putObject($previewVideoPath, $tempFile);
                        //     } finally {
                        //         // 清理临时文件
                        //         @unlink($tempFile);
                        //     }
                        // }
                        
                        // 上传成品视频
                        if (!empty($result['finishedVideoUrl'])) {
                            $finishedVideoContent = $this->downloadFileWithRetry($result['finishedVideoUrl']);
                            if ($finishedVideoContent === false) {
                                $finishedVideoUrl = $result['finishedVideoUrl'];
                            } else {
                                $finishedVideoPath = 'marketing_videos/finished/' . date('Ymd') . '/' . uniqid() . '.mp4';
                                
                                // 创建临时文件
                                $tempFile = tempnam(sys_get_temp_dir(), 'finished_');
                                file_put_contents($tempFile, $finishedVideoContent);
                                
                                try {
                                    $finishedVideoUrl = $ossService->putObject($finishedVideoPath, $tempFile);
                                } finally {
                                    // 清理临时文件
                                    @unlink($tempFile);
                                }
                            }
                        }
                        // 更新任务状态
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'video_status' => 2,
                                'overall_status' => 4, // 全部完成
                                'preview_video_url' => $previewVideoUrl ?? '',
                                'finished_video_url' => $finishedVideoUrl ?? '',
                                'video_complete_time' => date('Y-m-d H:i:s'),
                                'update_time' => date('Y-m-d H:i:s')
                            ]);
                        
                        $output->writeln("视频生成任务 {$task['video_task_id']} 已完成");
                        $checkedVideo++;
                        
                    } elseif ($result['status'] == 'failed' || $result['status'] == 'fail') { // 失败
                        Db::name('marketing_video_unified_tasks')
                            ->where('id', $task['id'])
                            ->update([
                                'video_status' => 3,
                                'overall_status' => 5, // 失败
                                'video_error_msg' => $result['errorMsg'] ?? '视频生成失败',
                                'update_time' => date('Y-m-d H:i:s')
                            ]);
                        
                        $output->writeln("视频生成任务 {$task['video_task_id']} 失败: " . ($result['errorMsg'] ?? '未知错误'));
                        $checkedVideo++;
                    }
                    
                } catch (\Exception $e) {
                    $output->writeln("检查视频生成任务 {$task['video_task_id']} 出错: " . $e->getMessage());
                }
            }

            $output->writeln("检查完成！去背景任务: {$checkedBg}个，图片替换任务: {$checkedReplace}个，视频生成任务: {$checkedVideo}个");
            
        } catch (\Exception $e) {
            $output->writeln('检查任务时发生错误: ' . $e->getMessage());
            return 1;
        }
        
        return 0;
    }

    /**
     * 使用cURL下载文件，带重试机制
     * @param string $url 下载URL
     * @param int $maxRetries 最大重试次数
     * @return string|false 文件内容或false
     */
    private function downloadFileWithRetry($url, $maxRetries = 10)
    {
        for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
            try {
                $ch = curl_init();
                curl_setopt_array($ch, [
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_SSL_VERIFYPEER => false,
                    CURLOPT_SSL_VERIFYHOST => false,
                    CURLOPT_TIMEOUT => 60, // 60秒超时
                    CURLOPT_CONNECTTIMEOUT => 30, // 30秒连接超时
                    CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    CURLOPT_HTTPHEADER => [
                        'Accept: */*',
                        'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
                        'Cache-Control: no-cache'
                    ],
                    CURLOPT_MAXREDIRS => 5,
                    CURLOPT_ENCODING => '', // 自动解压
                ]);

                $content = curl_exec($ch);
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $error = curl_error($ch);
                curl_close($ch);

                if ($content === false || !empty($error)) {
                    throw new \Exception("cURL错误: " . $error);
                }

                if ($httpCode >= 200 && $httpCode < 300) {
                    return $content;
                } else {
                    throw new \Exception("HTTP错误: " . $httpCode);
                }

            } catch (\Exception $e) {
                if ($attempt === $maxRetries) {
                    \think\facade\Log::error('下载文件失败', [
                        'url' => $url,
                        'attempt' => $attempt,
                        'error' => $e->getMessage()
                    ]);
                    return false;
                }
            }
        }
        
        return false;
    }
} 